package com.dianping.cat.local.integration.struts2;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;
import org.slf4j.LoggerFactory;

import com.dianping.cat.local.messagecodec.HtmlMessageCodec;
import com.dianping.cat.local.messagecodec.WaterfallMessageCodec;
import com.dianping.cat.local.persistence.CatLogService;
import com.dianping.cat.local.persistence.CatLogServiceFactory;
import com.dianping.cat.message.Transaction;
import com.dianping.cat.message.spi.MessageTree;
import com.opensymphony.xwork2.ActionSupport;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;

public class CatAction extends ActionSupport {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private final WaterfallMessageCodec m_waterfall = new WaterfallMessageCodec();

	private final HtmlMessageCodec m_html = new HtmlMessageCodec();

	//@Inject
	private CatLogService catLogService = CatLogServiceFactory.getSingleton();

	public CatAction() {
		m_html.setLogViewPrefix("/cat/catLog/");
	}

	public void catLog() {
		final String traceId = getRequest().getParameter("traceId");
		final HttpServletResponse response = ServletActionContext.getResponse();
		doDealCatLog(traceId, "true".equalsIgnoreCase(getRequest().getParameter("waterfall")), response);
	}

	private void doDealCatLog(String traceId, boolean waterfall, HttpServletResponse response) {
		final MessageTree mt = catLogService.find(traceId);
		writeContentToResponse(encodeTxt(mt, waterfall), response);
	}

	private String encodeTxt(MessageTree tree, boolean waterfall) {
		if (tree != null) {
			ByteBuf buf = ByteBufAllocator.DEFAULT.buffer(8192);

			if (tree.getMessage() instanceof Transaction && waterfall) {
				m_waterfall.encode(tree, buf);
			} else {
				m_html.encode(tree, buf);
			}

			try {
				buf.readInt(); // get rid of length
				return buf.toString(Charset.forName("utf-8"));
			} catch (Exception e) {
				// ignore it
			} finally {
				if (null != buf) {
					buf.release();
				}
			}
		}

		return "";
	}

	private void writeContentToResponse(String content, HttpServletResponse response) {
		// response.setContentType("application/xhtml+xml;charset=utf-8");
		response.setCharacterEncoding("utf-8");
		try (BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream())) {
			byte[] bytes = content.getBytes();
			bos.write(bytes, 0, bytes.length);
			bos.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void catTest(boolean isThrow) {
		final HttpServletResponse response = ServletActionContext.getResponse();

		LoggerFactory.getLogger(this.getClass()).info("进行CAT测试, 传入参数为: {} ", getRequest().getParameterMap());
		if (isThrow) {
			throw new RuntimeException("抛出異常, 验证CAT全链路日志");
		} else {
			writeContentToResponse("调用成功",response);
		}

	}

	/**
	 * 获取 HttpServletRequest
	 *
	 * @return {HttpServletRequest}
	 */
	static HttpServletRequest getRequest() {
		return ServletActionContext.getRequest();
	}

}